package com.yehebl.orm.data.common.xml.manager;

import com.yehebl.orm.data.common.xml.dto.XmlSql;
import com.yehebl.orm.util.ConfigListenerUtil;
import com.yehebl.orm.util.LogUtil;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;


/**
 * xml 管理
 */
public class XmlSqlManager {
	private static final Map<String, XmlSql> xmlSqlMap = new HashMap<>();
	private static final XmlSql defaultXmlSql=new XmlSql(new HashMap<>());

	
	//避免重复扫描
	private static final Set<String> xmlFileUrl=new HashSet<>();

	public static void HotXml(Set<String> list) {
		for (String fileUrl : list) {
			ConfigListenerUtil.listen(fileUrl, XmlSqlManager::reloadXml);
		}
	}

	public static XmlSql getSqlByName(String sqlName) {
		XmlSql xmlSql = xmlSqlMap.get(sqlName);
		if(xmlSql!=null) {
			return xmlSql;
		}
		if("defaultXmlSql".equals(sqlName)) {
			return defaultXmlSql;
		}
		return null;
	}

	public static void readXml(String fileUrl) {
		if (fileUrl == null) {
			return;
		}
		if(xmlFileUrl.contains(fileUrl)){
			LogUtil.printInfo(fileUrl+"已被加载");
			return;
		}
		xmlFileUrl.add(fileUrl);
		LogUtil.printInfo("正在加载：" + fileUrl);
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db;
		try {
			db = dbf.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			throw new RuntimeException(e);
		}
		// 将xml文件解析
		Document document;
		try {
			document = db.parse(new File(fileUrl));
		} catch (SAXException | IOException e) {
			throw new RuntimeException(e);
		}
		// 获得所有节点，递归遍历节点
		NodeList employees = document.getChildNodes();
		for (int i = 0; i < employees.getLength(); i++) {
			// 取得一个节点
			Node employee = employees.item(i);
			NodeList employeeInfo = employee.getChildNodes();
			for (int j = 0; j < employeeInfo.getLength(); j++) {
				if (employeeInfo.item(j).getNodeName().equals("sql-query")) {
					NamedNodeMap attributes = employeeInfo.item(j).getAttributes();
					String keyName = null;
					XmlSql xs = new XmlSql();
					Map<String, String> attributesMap = new HashMap<>();
					for (int k = 0; k < attributes.getLength(); k++) {
						if (attributes.item(k).getNodeName().equals("name")) {
							keyName = attributes.item(k).getNodeValue();
						}
						attributesMap.put(attributes.item(k).getNodeName(), attributes.item(k).getNodeValue());
					}
					xs.setSqlKey(keyName);
					xs.setSql(employeeInfo.item(j).getTextContent());
					xs.setXmlFileUrl(fileUrl);
					xs.setAttributesMap(attributesMap);
					if (xmlSqlMap.containsKey(keyName)) {
						throw new Error("[" + keyName + "]重复的sql Name文件：" + fileUrl);
					}
					xmlSqlMap.put(keyName, xs);
				}
			}
		}
	}

	public static void reloadXml(File file) {
		LogUtil.printInfo("正在重新加载：" + file.getPath());
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db;
		try {
			db = dbf.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			throw new RuntimeException(e);
		}
		// 将xml文件解析
		Document document;
		try {
			document = db.parse(file);
		} catch (SAXException | IOException e) {
			throw new RuntimeException(e);
		}
		// 获得所有节点，递归遍历节点
		NodeList employees = document.getChildNodes();
		for (int i = 0; i < employees.getLength(); i++) {
			// 取得一个节点
			Node employee = employees.item(i);

			NodeList employeeInfo = employee.getChildNodes();
			for (int j = 0; j < employeeInfo.getLength(); j++) {
				if (employeeInfo.item(j).getNodeName().equals("sql-query")) {
					NamedNodeMap attributes = employeeInfo.item(j).getAttributes();
					String keyName = null;
					XmlSql xs = new XmlSql();
					Map<String, String> attributesMap = new HashMap<>();
					for (int k = 0; k < attributes.getLength(); k++) {
						if (attributes.item(k).getNodeName().equals("name")) {
							keyName = attributes.item(k).getNodeValue();
						}
						attributesMap.put(attributes.item(k).getNodeName(), attributes.item(k).getNodeValue());
					}
					xs.setSqlKey(keyName);
					xs.setSql(employeeInfo.item(j).getTextContent());
					xs.setXmlFileUrl(file.getPath());
					xs.setAttributesMap(attributesMap);
					xmlSqlMap.put(keyName, xs);
				}
			}
		}
	}

	public static void scanQueryXmlFile(String url, Set<String> resultList) {
		File f = new File(url);
		if (!f.isDirectory()) {
			if (!f.getPath().endsWith(".xml")) {
				return;
			}
			resultList.add(f.getPath());
		} else {
			String[] fileList = f.list();
			if (fileList == null) {
				return;
			}
			for (String s : fileList) {
				String path = f.getAbsolutePath() + File.separator + s;
				scanQueryXmlFile(path, resultList);
			}
		}
	}

	public static void readXml(String path, InputStream resourceAsStream) {
		if (resourceAsStream == null) {
			return;
		}
		if(xmlFileUrl.contains(path)){
			LogUtil.printInfo(path+"已被加载");
			return;
		}
		xmlFileUrl.add(path);
		LogUtil.printInfo("正在加载：" + path+",无法热更");
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db;
		try {
			db = dbf.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			throw new RuntimeException(e);
		}
		// 将xml文件解析
		Document document;
		try {
			document = db.parse(resourceAsStream);
		} catch (SAXException | IOException e) {
			throw new RuntimeException(e);
		}
		// 获得所有节点，递归遍历节点
		NodeList employees = document.getChildNodes();
		for (int i = 0; i < employees.getLength(); i++) {
			// 取得一个节点
			Node employee = employees.item(i);

			NodeList employeeInfo = employee.getChildNodes();
			for (int j = 0; j < employeeInfo.getLength(); j++) {
				if (employeeInfo.item(j).getNodeName().equals("sql-query")) {
					NamedNodeMap attributes = employeeInfo.item(j).getAttributes();
					String keyName = null;
					XmlSql xs = new XmlSql();
					Map<String, String> attributesMap = new HashMap<>();
					for (int k = 0; k < attributes.getLength(); k++) {
						if (attributes.item(k).getNodeName().equals("name")) {
							keyName = attributes.item(k).getNodeValue();
						}
						attributesMap.put(attributes.item(k).getNodeName(), attributes.item(k).getNodeValue());
					}
					xs.setSqlKey(keyName);
					xs.setSql(employeeInfo.item(j).getTextContent());
					xs.setXmlFileUrl(path);
					xs.setAttributesMap(attributesMap);
					if (xmlSqlMap.containsKey(keyName)) {
						throw new Error("[" + keyName + "]重复的sql Name文件：" + path);
					}
					xmlSqlMap.put(keyName, xs);
				}
			}
		}
	}

}
